home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Apple II Magazines (PO)
/
Nibble Volume 11, No. 08 (1990-08)(MindCraft Publishing)(Side A).zip
/
Nibble Volume 11, No. 08 (1990-08)(MindCraft Publishing)(Side A).po
/
VIRT.MEM.S
< prev
Wrap
Text File
|
1996-12-24
|
24KB
|
923 lines
********************************
* VIRT.MEM.OBJ SOURCE CODE *
* BY JOHN R. VOKEY *
* COPYRIGHT (C) 1990 *
* MINDCRAFT PUBL. CORP. *
* CONCORD, MA 01742 *
********************************
* (Merlin 8/16 assembler)
*===============================
* Equates
*===============================
*--------Applesoft BASIC--------
TXTPTR equ $B8
INDEX equ $5E
CHKSTR equ $DD6C
FRETMP equ $E604
MEMERR equ $D410
ERROR equ MEMERR+2
NOTFOUND equ $E1B8
ARYFOUND equ $E19E
CHKCOM equ $DEBE
CHRGOT equ $B7
DIMFLG equ $10
VARNAM equ $81
ISLETC equ $E07D
SYNERR equ $DEC9
VALTYP equ $11
INTFLG equ $12
CHRGET equ $B1
MAKINT equ $E102
FAC equ $9D
GETARY equ $E0ED
GETARY2 equ $E0EF
GETARYPT equ $F7D9
PTRGET equ $DFE3
ARYPNT equ $94
REASON equ $D3E3
STREND equ $6D
LOWTR equ $9B
STACK equ $100
NUMDIM equ $0F
SUBFLG equ $14
CHKCLS equ $DEB8
FRMEVL equ $DD7B
HIMEM equ $73
ARYTAB equ $6B
BACKIN1 equ $E03F
SUBERR equ $E196
MORNAM equ $E007
VARPNT equ $83
NCLEAR equ $D66C
AMPER equ $3F5
SAVE equ 183
STORE equ 168
CLEAR equ 189
*---------Internal Zpage--------
savex equ 3
temp equ 4
Product equ $EB
Multiplicand equ $17
Multiplier equ $06
*-----------Monitor-------------
A1L equ $3C
Move_Start equ A1L
A2L equ $3E
Move_End equ A2L
A4L equ $42
Move_To equ A4L
MOVE equ $FE2C
PCL equ $3A
INSDS2 equ $F88C
LENGTH equ $2F
PCADJ equ $F953
COUT equ $FDED
cr equ $8D
*------ProDOS and BASIC.SYSTEM------
GOSYSTEM equ $BE70
Memory_Top equ $96
ERROUT equ $BE09
BADCALL equ $BE8B
GETBUFR equ $BEF5
File_Type equ $FD ;make it a VAR file
SREAD equ $BED5
DATE equ $BF90
TIME equ $BF92
Disk_Block equ 2 ;in pages
Half_Block equ Disk_Block/2
BITMAP equ $BF58
OFILACTV equ $BE45
TBUFPTR equ $BE4A
MACHID equ $BF98
create equ $C0
getinfo equ $C4
write equ $CB
open equ $C8
setmark equ $CE
read equ $CA
close equ $CC
*===============================
* Install and Init
*===============================
use virt.macs ;macro file
dsk Virt.Mem.obj ;object file name
org $4000
Installed?
mov #Memory_Top;temp+1
mov #0 ;temp
:1 ldy #5
:2 lda (temp),Y ;check sig bytes
cmp Virtual_Array,Y
bne :3
dey
bpl :2
jmp Copyright ;installed already, exit
:3 dec temp+1
lda temp+1
cmp HIMEM+1
bcs :1
Get_Space
lda #>End-Virtual_Array+$100
jsr GETBUFR
bcc :1
jmp ERROUT ;crash on error
:1 sta CHRGET+2 ;save page #
sta A1L
sec ;compute how far
sbc #>Virtual_Array ; to move code
sta temp ; and save for later.
Protect_Space
mov #>End-Virtual_Array+$100;A1L+1
:1 lda A1L
pha
lsr
lsr
lsr
tax
pla
eor #$FF
and #7
sec
tay
lda #0
:2 rol
dey
bpl :2
ora BITMAP,X
sta BITMAP,X
inc A1L ;do for all pages
dec A1L+1
bne :1
Fix_Addresses
movd AMPER+1 ;Daisy_Chain+1
mov #<Virtual_Array;PCL
mov #>Virtual_Array;PCL+1
:1 ldx #0
jsr INSDS2 ;disassemble one instruction
lda (PCL),Y ;BRK?
beq Relocate_Code ;yes, move it
ldy LENGTH ;3-byte instruction?
cpy #2
bne :2 ;no, next
lda (PCL),Y ;yes, is it within
cmp #>Virtual_Array ; the code?
bcc :2 ;no, do next
cmp #>End+$100
bcs :2 ;no, do next
clc ;else, fix address
adc temp
sta (PCL),Y
:2 jsr PCADJ ;get next instruction
sta PCL ;point to it
sty PCL+1
jmp :1 ;and go again
Relocate_Code
ldy #0 ;set up monitor move
sty A1L
mov #>Virtual_Array;A1L+1
mov #<End ;A2L
mov #>End ;A2L+1
sty A4L
mov CHRGET+2 ;A4L+1
sta AMPER+2
jsr MOVE ;and move code.
mov #$4C ;CHRGET ;set vectors
sta AMPER
mov #<Virtual_Array;CHRGET+1
mov #<Amper_Interp;AMPER+1
Copyright
print cr,cr
print " Virtual Memory"
print cr
print " for Applesoft BASIC"
print cr
print " Version 2.0"
print cr,cr
print " by John R. Vokey"
print cr
print " Copyright 1990 MindCraft Publ."
print cr,cr
rts ;back to basic
sendmsg pull temp
bne :3
:1 bit MACHID ;flag // and //+
bmi :2 ;//e or greater
cmp #$E0 ;convert to upper-case
bcc :2
and #$DF
:2 jsr COUT
:3 ldy #0
incr temp
lda (temp),Y
bne :1
push temp
rts
lst off
ds \ ;skip to next page boundary
lst on
*=================================
* Virtual_Array
*=================================
Virtual_Array
pull temp ;retrieve caller
cmp #>MORNAM ;from MORNAM?
bne :1 ;no, exit
lda #<MORNAM+2
cmp temp
beq VirtualArray? ;yes, do it
:1 push temp ;restore return address
incr TXTPTR ;complete CHRGET
jmp CHRGOT
Amper_Interp
cmp #STORE ;flush a virtual array?
bne :1
jmp Store_Token
:1 cmp #CLEAR ;clear variables?
bne :2
jmp Clear_Token
:2 cmp #SAVE ;create a virtual array?
bne Daisy_Chain
jmp Save_Token
Daisy_Chain
jmp SYNERR ;daisy-chain '&' calls
VirtualArray?
jsr More_Name ;complete MORNAM
ora VALTYP ;simple var or string array?
beq :1 ;no, check for array
jsr CHRGOT ;else, recover char
jmp BACKIN1 ; and exit.
;
:1 jsr ARRAY2 ;process the array
bcc :2 ;if found, continue
jmp NOTFOUND else, exit
:2 ldy #4 ;check numdim
lda (LOWTR),Y ;not a virtual array?
ora DIMFLG ;dimension it?
ora SUBFLG ;from GETARYPT?
beq :3 ;if all no, continue
jmp ARYFOUND else, exit
:3 iny ;it's a virtual array!
lda (LOWTR),Y ;get true num dims
cmp NUMDIM ;same as requested?
beq Check_Dims ;yes, continue
Do_SUBERR jmp SUBERR ;else, subscript error
Check_Dims
mov #0 ;Product ;clear mult locs
sta Product+1
sta Product+2
:1 pla ;low byte of index
tax
sta FAC+3
pla ;get high byte
sta FAC+4
iny
cmp (LOWTR),Y ;< = DIM?
bcc :2 ;yes, do it
bne Do_SUBERR ;else, SUBSCRIPT error
iny
txa
cmp (LOWTR),Y ;<DIM?
bcs Do_SUBERR ;no, SUBSCRIPT error
dey ;point to high byte
:2 mov (LOWTR),Y ;Multiplier+1
iny
mov (LOWTR),Y ;Multiplier
lda Product ;first pass?
ora Product+1
ora Product+2
beq :3 ;yes, branch
jsr Mult_16x24 ;else, multiply dims
:3 clc
lda FAC+3 ;add in number of each
adc Product
sta Product
lda Product+1
adc FAC+4
sta Product+1
lda Product+2
adc #0
sta Product+2
dec NUMDIM ;next dimension
bne :1
ldx #5 ;assume real array
lda VARNAM ;is it?
bpl :4 ;yes, continue
ldx #2 ;else, integer array
:4 stx Multiplier ;DIMS * size (X)
stx savex ;save type for later
mov #0 ;Multiplier+1 ;set up last MULT
jsr Mult_16x24 ;and do it
ldy #5 ;recover NUMDIM
mov (LOWTR),Y ;NUMDIM
DataInMemory?
jsr GETARY ;point to internal vars
ldy #3 ;Product < CURBYTE?
:1 lda Product-1,Y
cmp (ARYPNT),Y
bcc :4 ;yes, get new block
bne :2 ;else, check high end
dey
bne :1
:2 sec ;compute # bytes
lda #0 ;subtract size
sbc savex
sta Multiplicand
lda #Disk_Block
sbc #0
sta Multiplicand+1
clc
ldy #1 ;compute high end
lda (ARYPNT),Y
adc Multiplicand
sta Multiplicand
iny
lda (ARYPNT),Y
adc Multiplicand+1
sta Multiplicand+1
iny
lda (ARYPNT),Y
adc #0
sta Multiplicand+2
dey
:3 lda Product,Y ;Product < End?
cmp Multiplicand,Y
bcc ComputeOffset ;yes, continue
bne :4 ;else, get data
dey
bpl :3
:4 jsr Array_Write ;WRITE back old block
jsr Array_Read2 ;READ in new block
ComputeOffset
sec
ldy #1
lda Product
sbc (ARYPNT),Y
sta VARPNT
lda Product+1
iny
sbc (ARYPNT),Y
sta VARPNT+1
jsr Pnt_to_Data ;point to data
clc
lda ARYPNT ;compute offset to value
adc VARPNT
sta VARPNT
lda ARYPNT+1
adc VARPNT+1
sta VARPNT+1
tay
lda VARPNT
rts ;return as BASIC expects
Store_Token
jsr CHRGET ;move TXTPTR to name
:1 jsr GETARYPT ;find array (error if none)
ldy #4
lda (LOWTR),Y ;is it virtual?
beq :2 ;yes, continue
ldx #128 ;else
jmp ERROR ;make 'ARRAY ERROR'
:2 iny ;get NUMDIM
mov (LOWTR),Y ;NUMDIM
jsr Array_Write ;write the data
jsr Array_Close ;close virtual file
jsr CHRGOT ;check for more
bne :3
rts
:3 jsr CHKCOM ;must be comma
jmp :1
Clear_Token
jsr CHRGET ;move TXTPTR to var name
bne :1 ;exit if normal CLEAR
jmp NCLEAR
:1 jsr PTRGET ;get var
cpy ARYTAB+1 ;simple or array var?
bne :2 ;flag in carry (set = array)
cmp ARYTAB
:2 ldy #2
php
bcs :3 ;array var, go
lda #0 ;create dummy offset for
iny ;simple vars
sta (LOWTR),Y
dey
lda #7
sta (LOWTR),Y
:3 clc
lda (LOWTR),Y ;get offset to next var
sta temp
lda LOWTR ;set up move
sta Move_To
adc temp
sta Move_Start
lda LOWTR+1
sta Move_To+1
iny
adc (LOWTR),Y
sta Move_Start+1
lda (LOWTR),Y
sta temp+1
ldy #0
lda STREND
sta Move_End
lda STREND+1
sta Move_End+1
jsr MOVE ;and move, erasing var
lda STREND ;set STREND to new val
sbc temp
sta STREND
lda STREND+1
sbc temp+1
sta STREND+1
plp ;recover simple or array
bcs :4 ;if simple, fix ARYTAB
lda ARYTAB
sbc #6
sta ARYTAB
bcs :4
dec ARYTAB+1
:4 jsr CHRGOT ;more?
bne :5
rts
:5 jsr CHKCOM ;must be comma
jmp :1
Save_Token
jsr CHRGET ;move TXTPTR to name
jsr FRMEVL ;evaluate it
jsr CHKSTR ;must be string
ldy #0 ;save length and handle
mov (FAC+3),Y ;templength
movd FAC+3 ;temphandle
jsr CHKCOM ;comma?
sta DIMFLG ;set dimflg
sta VARNAM ;save 1st char of var
jsr ISLETC ;letter?
bcs NAMOK ;yes, continue
BADNAM jmp SYNERR ;no, bad name
NAMOK ldx #0
stx VALTYP ;clear flags
stx INTFLG
jsr More_Name ;process second char
ora VALTYP ;simple var or string?
bne BADNAM ;yes, error
jsr ARRAY2 ;process array
bcs :1 ;not found, continue
jmp ARYFOUND ;else, error
:1 jsr New_GETARY
lda templength ;recover pathname length
jsr Pnt_to_Data2
adc #1
sta temp
tya
adc #Disk_Block
sta temp+1
tay
lda temp
jsr REASON ;enough room for array?
SaveArrayInfo
ldy #0
sty Product+1 (clear mult Product)
sty Product+2
ldx #5 ;assume real array
mov VARNAM ;(LOWTR),Y ;get first char
bpl :1 ;if real, go
ldx #2 ;else, integer array
:1 iny
mov VARNAM+1 ;(LOWTR),Y
iny ;point to offset locs
sec ;calculate offset
lda temp ;recover last byte
sbc LOWTR ;subtract first byte
sta (LOWTR),Y ;offset to next var
iny
lda temp+1
sbc LOWTR+1
sta (LOWTR),Y
iny
mov #0 ;(LOWTR),Y ;flag virtual array
iny ;save true numdim
mov NUMDIM ;(LOWTR),Y ;one byte later
stx Product ;for mult (DIMS * size)
CalculateSize
pla ;recover lbyte of dim
clc
adc #1 ;plus 1
tax ;save temporarily
pla ;hbyte of dim
adc #0
iny
sta (LOWTR),Y ;save hbyte of dim
sta Multiplier+1 ;and in Multiplier (for mult)
iny
txa
sta (LOWTR),Y ;save lbyte of dim
sta Multiplier ;and in Multiplier
jsr Mult_16x24 ;DIM * OLD Product
dec NUMDIM ;next dimension
bne CalculateSize
SaveArrayPrms
lda #0 ;do CURBYTE
ldx #3
:1 iny
sta (LOWTR),Y
dex
bpl :1
iny
mov #Disk_Block;(LOWTR),Y ;set NUMBYTES
ldy #5 ;recover NUMDIM
mov (LOWTR),Y ;NUMDIM
jsr New_GETARY ;point to name buf
lda temphandle ;recover handle
ldy temphandle+1
jsr FRETMP ;and dispose of it
ldy #0
sta (ARYPNT),Y ;save pathname length
tay
:2 dey
lda (INDEX),Y ;save pathname
iny
sta (ARYPNT),Y
dey
bne :2
jsr Pnt_to_Data
ldx #Disk_Block
lda #0
tay
:3 sta (ARYPNT),Y ;clear array
iny
bne :3
inc ARYPNT+1
dex
bne :3
Create_File
jsr New_GETARY ;point to pathname
movd ARYPNT ;createparms+1
movd ARYPNT ;getinfoparms+1
movd ARYPNT ;openparms+1
movd DATE ;createparms+8
movd TIME ;createparms+10
go_dos create ;createparms
bcc :3
cmp #19 ;Duplicate file error?
bne :2 ;no, crash
go_dos getinfo ;getinfoparms
lda getinfoparms+4 ;get file type
cmp #File_Type
bne :1 ;if not virtual, crash
lda getinfoparms+6
cmp #"V" ;'V'irtual
bne :1
lda getinfoparms+5
cmp #"A" ;'A'rray?
bne :1
jsr Set_STREND ;else, set STREND
jmp Array_Read ; and read in block 1
:1 lda #19 ;else, crash
:2 jmp ERROUT
:3 clc
ror Product+2
ror Product+1
jsr Array_Open ;open file
jsr Pnt_to_Data ;point to data
sta writeparms+2
sty writeparms+3
mov #0 ;writeparms+4
mov #Disk_Block;writeparms+5
:4 go_dos write ;writeparms ;write it
bcc :5
jmp Read_Error
:5 lda Product+1
ora Product+2
beq :7 ;do for all blocks
lda Product+1
bne :6
dec Product+2
:6 dec Product+1
jmp :4
:7 jsr Array_Close
Set_STREND
movd temp ;STREND
rts ;and back to BASIC
More_Name ;replaces Applesoft MORNAM
jsr CHRGET
bcc OV
jsr ISLETC
bcc STR
OV tax
BY jsr CHRGET
bcc BY
jsr ISLETC
bcs BY
STR cmp #'$'
bne INTV
mov #$FF ;VALTYP
bne NIN
INTV cmp #'%'
bne SECND
lda SUBFLG
bpl MINTV
jmp SYNERR
MINTV mov #$80 ;INTFLG
ora VARNAM
sta VARNAM
NIN txa
ora #$80
tax
jsr CHRGET
SECND stx VARNAM+1
sec
ora SUBFLG
sbc #'('
rts
ARRAY2 ;replaces Applesoft ARRAY code
;to allow arrays >64k
lda SUBFLG
bne FNDARY2
lda DIMFLG
ora INTFLG
pha
lda VALTYP
pha
ldy #0
NXTDIM tya
pha
push VARNAM
jsr MAKINT
pull VARNAM
pla
tay
tsx
lda STACK+2,X
pha
lda STACK+1,X
pha
lda STACK+4,X
sta STACK+2,X
lda STACK+3,X
sta STACK+1,X
mov FAC+3 ;STACK+4,X
mov FAC+4 ;STACK+3,X
iny ;counts dim number
jsr CHRGOT
cmp #','
beq NXTDIM
sty NUMDIM
jsr CHKCLS
pull VALTYP
and #$7F
sta DIMFLG
FNDARY2 ldx ARYTAB
lda ARYTAB+1
ARYLOOP stx LOWTR
sta LOWTR+1
cmp STREND+1
bne ARYNAM
cpx STREND
beq NOTFND2
ARYNAM ldy #0
lda (LOWTR),Y
iny
cmp VARNAM
bne NXARY
lda VARNAM+1
cmp (LOWTR),Y
beq ARYFND2
NXARY iny
lda (LOWTR),Y
clc
adc LOWTR
tax
iny
lda (LOWTR),Y
adc LOWTR+1
bcc ARYLOOP
ARYFND2 clc ;Flag found array
NOTFND2 rts
Mult_16x24
ldx #2 ;Product -> Multiplicand
:1 mov Product,X ;Multiplicand,X
dex
bpl :1
MUL ldx #4 ;alternate entry
lda #0
:2 sta Product,X
dex
bpl :2
ldx #16 ;16-bit Multiplier
:3 lsr Multiplier+1
ror Multiplier
bcc :4
clc
lda Product+2
adc Multiplicand
sta Product+2
lda Product+3
adc Multiplicand+1
sta Product+3
lda Product+4
adc Multiplicand+2
sta Product+4
:4 lsr Product+4
ror Product+3
ror Product+2
ror Product+1
ror Product
dex
bne :3
lda Product+3
ora Product+4 ; > 16 meg (ProDOS limit)?
beq NOTFND2 ; no, exit
jmp MEMERR ; yes, memory error
Array_Open
lda OFILACTV ;active output file?
beq :1 ;no, open virtual file
lda TBUFPTR ;Yes, bytes buffered?
beq :1 ;no, open virtual file
sta SREAD+4 ;Yes, store how many
mov #0 ;SREAD+5
go_sys write ;and WRITE them.
bcs Open_Error
lda #0 ;clear buffered byte count
sta TBUFPTR
:1 jsr New_GETARY ;get pathname pointer
sta openparms+1
sty openparms+2
mov #0 ;openparms+3 ;set OPEN parameters
mov HIMEM+1 ;openparms+4
go_dos open ;openparms ;open file
bcs Open_Error
lda openparms+5 ;recover REFNUM
sta readparms+1 ;and save within other
sta closeparms+1 ;globals
sta setmrkparms+1
rts
Open_Error jmp ERROUT
Array_Read
jsr Array_Open ;OPEN file
Array_Read2 mov Product ;setmrkparms+2
lda Product+2 ;set MARK
ora Product+1
bne :1
sta setmrkparms+2 ;to zero
sta setmrkparms+3 ;if first block
beq :2
:1 lda Product+1 ;else, load a block
sec ;with requested value
sbc #Half_Block ;at midpoint
sta setmrkparms+3
lda Product+2
sbc #0
:2 sta setmrkparms+4
go_dos setmark ;setmrkparms
bcs Read_Error
mov #0 ;readparms+4
mov #Disk_Block;readparms+5
jsr Pnt_to_Data ;point to data
sta readparms+2
sty readparms+3
go_dos read ;readparms ;and read it
bcc :3
cmp #5 ;end of data?
bne Read_Error
:3 jsr GETARY ;mark CURBYTE & NUMBYTES
ldy #1
mov setmrkparms+2;(ARYPNT),Y
iny
mov setmrkparms+3;(ARYPNT),Y
iny
mov setmrkparms+4;(ARYPNT),Y
iny
mov readparms+6;(ARYPNT),Y
iny
mov readparms+7;(ARYPNT),Y
lda #0
Read_Error pha ;save error code
jsr Array_Close ;CLOSE file
pla ;recover error code
bne Close_Error ;if error, go
rts
Array_Write
jsr Array_Open
Array_Write2 jsr GETARY
ldy #1
mov (ARYPNT),Y ;setmrkparms+2
iny
mov (ARYPNT),Y ;setmrkparms+3
iny
mov (ARYPNT),Y ;setmrkparms+4
iny
mov (ARYPNT),Y ;writeparms+4
iny
mov (ARYPNT),Y ;writeparms+5
go_dos setmark ;setmrkparms
bcs Read_Error
jsr Pnt_to_Data ;point to DATA
sta writeparms+2
sty writeparms+3
go_dos write ;writeparms ;and write it
bcs Read_Error
an_rts rts
Array_Close
go_dos close ;closeparms ;CLOSE virtual file
bcc an_rts
Close_Error jmp ERROUT
Pnt_to_Data
jsr New_GETARY
ldy #0
lda (ARYPNT),Y ;get name length
clc
adc #1
Pnt_to_Data2
clc
adc ARYPNT ;add to current loc
sta ARYPNT
lda ARYPNT+1
adc #0
sta ARYPNT+1
tay ;save hbyte
lda ARYPNT ;and lbyte
rts
New_GETARY lda NUMDIM
clc
adc #3
jmp GETARY2
do_dos sta *+6
jsr $BF00
lda createparms ;dummy code for relocate
bcc an_rts
jmp BADCALL ;translate error code
templength ds 1
temphandle ds 2
createparms db 7
dw 0
db $C3,$FD
asc "AV"
db 1
dw 0,0
getinfoparms
db $A
ds 17
setmrkparms
db 2,0,0,0,0
openparms
db 3
ds 5
readparms
writeparms
db 4,0
dw 0,0,0
closeparms
db 1,0
chk ;checksum byte (= $E5)
End
lst off ;kill symbol table